package com.gxa.autoparts.portal.controller;
import com.gxa.autoparts.core.common.ExceptionCode;
import com.gxa.autoparts.core.common.JsonResult;
import com.gxa.autoparts.core.exception.BusinessException;
import lombok.extern.log4j.Log4j2;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.Errors;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Map;
import java.util.Set;


/**
 * @author R
 * @data 2021-10-21 15:21
 */
@RestController
@ControllerAdvice
@Slf4j
public class ExceptionController {

    // 处理第一种校验异常: 将异常信息拼接,返回给前端显示
    @ExceptionHandler({BindException.class, MethodArgumentNotValidException.class})
    public Map handleBindException(Errors errors){
        JsonResult jsonResult = new JsonResult();
        jsonResult.setCode("100");
        StringBuilder stringBuilder = new StringBuilder();
        errors.getAllErrors().forEach(error->{
            stringBuilder.append(error.getDefaultMessage()+",");
        });
        //除去多余的逗号
        String errorMessage = stringBuilder.toString().substring(0, stringBuilder.toString().length()-1);
        jsonResult.setMsg(errorMessage);
        return jsonResult.getDataMap();
    }

    // 处理第二种校验异常: 将异常信息拼接,返回给前端显示
    @ExceptionHandler(ConstraintViolationException.class)
    public Map handleConstraintViolationException(ConstraintViolationException exception) {
        StringBuilder errorInfo = new StringBuilder();
        String errorMessage ;

        Set<ConstraintViolation<?>> violations = exception.getConstraintViolations();
        for (ConstraintViolation<?> item : violations) {
            errorInfo.append(item.getMessage()).append(",");
        }

        errorMessage = errorInfo.toString().substring(0, errorInfo.toString().length()-1);
        JsonResult jsonResult = new JsonResult();
        jsonResult.setCode("100");
        jsonResult.setMsg(errorMessage);

        return jsonResult.getDataMap();
    }

    /**
     * 本质上就是一个aop的通知，专门用于加强异常出现的时候的抛出通知
     * 当有异常发生，抛出通知介入到目标操作
     * 并把异常对象注入到参数Exception中
     */
    @ExceptionHandler(BusinessException.class)
    public Map businessHandler(BusinessException e)  {

        JsonResult jsonResult = new JsonResult();
        ExceptionCode exceptionCode = e.getExceptionCode();
        jsonResult.setCode(exceptionCode.getCode());
        jsonResult.setMsg(exceptionCode.getMessage());
        return jsonResult.getDataMap();

    }

    @ExceptionHandler(Exception.class)
    public Map exceptionHandler(Exception e)  {


        //分割线
        log.info("-----------------begin-----------------------");
        // 先记录异常对象的toString状态: 包括异常类型和异常原因
        log.info(e.getMessage());
        // 再遍历栈中的异常轨迹: 采用遍历方式
        StackTraceElement[] stackTrace = e.getStackTrace();
        for (StackTraceElement stackTraceElement : stackTrace) {
            log.info(stackTraceElement.toString());
        }
        //分割线方便阅读
        log.info("-------------------end---------------------");

        JsonResult jsonResult = new JsonResult();
        jsonResult.setCode(ExceptionCode.SERVER_FAILED.getCode());
        jsonResult.setMsg(ExceptionCode.SERVER_FAILED.getMessage());
        return jsonResult.getDataMap();
    }
}




